/**
 * Copyright (c) 2016 Lenovo Group
 * All Rights Reserved.
 * 
 * Project Name:event-recorder
 * Create Time: 2016年4月29日 上午11:17:41
 */
package com.lenovo.lmrp.server.eventrecorder.domain.ticket;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.inject.Inject;
import com.lenovo.lmrp.api.model.entity.AssigningTicketPO;
import com.lenovo.lmrp.api.model.entity.ExceptionEventPO;
import com.lenovo.lmrp.api.model.entity.TicketPO;
import com.lenovo.lmrp.api.model.view.ExceptionEventContent;
import com.lenovo.lmrp.base.ParamNameDef;
import com.lenovo.lmrp.base.event.EventContent;
import com.lenovo.lmrp.base.event.EventTopic;
import com.lenovo.sdc.framework.mq.AMQClient;
import com.lenovo.sdc.framework.mq.IMQReceiver;
import com.lenovo.sdc.framework.sns.EMail;
import com.lenovo.sdc.framework.sns.MailSender;
import com.lenovo.sdc.framework.util.AttributeBean;
import com.lenovo.sdc.framework.util.CommonUtil;
import com.lenovo.sdc.framework.util.JSONHelper;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

/**
 * @author zhangzheng
 *
 */
public class ExceptionEventService implements IMQReceiver{
    
    private final static Logger logger = LoggerFactory.getLogger(ExceptionEventService.class);
    
    private BatchWriter<ExceptionEventPO> batchWriter;
    private AttributeBean attributes;
    
    @Inject
    public ExceptionEventService(AMQClient mqclient, IEventRepository repository) {
        mqclient.subscribe(EventTopic.EXCEPTION.name(), this);
        batchWriter = new ExceptionEventBatchWriter(repository);
        batchWriter.start();
    }
    @Inject
    public void set(AttributeBean attributes) {
        this.attributes = attributes;
    }
    
    @Override
    public void onMessage(String topic, Object content) {
        try {
            if (String.class.isInstance(content)) {
                EventContent<?> event = JSONHelper.fromJSON((String)content, EventContent.class);
                switch (event.getCode()) {
                    //抢单超时的异常工单
                    case EXCEPTION_TICKET_OVERTIME:
                        logger.debug("recv over time tickets {}",content);
                        Map<String, List<AssigningTicketPO>> ovts = JSONHelper.convertToObject(event.getContent(), new TypeReference<Map<String,List<AssigningTicketPO>>>() {});
                        Set<String> ticketIds = new HashSet<>();
                        for (String k : ovts.keySet()) {
                            List<AssigningTicketPO> pos = ovts.get(k);
                            for (AssigningTicketPO assigningTicketPO : pos) {
                                ticketIds.add(assigningTicketPO.getTicketId());
                            }
                        }
                        this.sendEmailForExceptionalTickets("工单" + Arrays.toString(ticketIds.toArray()) + "异常,35分钟未被处理.");
                        return;
                    case EXCEPTION_TICKET_NOWORKFLOW:
                        logger.debug("recv no workflow tickets {}",content);
                        Map<String, List<TicketPO>> nwfs = JSONHelper.convertToObject(event.getContent(), new TypeReference<Map<String,List<TicketPO>>>() {});
                        Set<String> ids = new HashSet<>();
                        for (String k : nwfs.keySet()) {
                            List<TicketPO> pos = nwfs.get(k);
                            for (TicketPO po : pos) {
                                ids.add(po.getId());
                            }
                        }
                        this.sendEmailForExceptionalTickets("工单" + Arrays.toString(ids.toArray()) + "异常,未能成功创建工作流.");
                        return;
                    //itsm Adapter 处理工单数据异常
                    case EXCEPTION_HANDLEDATA:
                        ExceptionEventContent eventContent = JSONHelper.convertToObject(event.getContent(), ExceptionEventContent.class);
                        if (eventContent.getMethod().equals("handleTicket")) {
                            Map<String, Object> others = eventContent.getOthers();
                            this.sendEmailForExceptionalTickets("工单[" + others.get("ticketid") + "]异常,itsmGateWay处理失败.");
                        }
                        ExceptionEventPO eventPO = new ExceptionEventPO();
                        eventPO.setEcode(eventContent.getErrorCode());
                        eventPO.setError(eventContent.getErrorMessage());
                        eventPO.setItsmCode(eventContent.getItsmcode());
                        eventPO.setSource(event.getSource().name());
                        this.batchWriter.push(eventPO);
                        return;
                    default:
                        logger.info("ignore {}", event.getCode());
                }
            }
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.MQ_ERROR, "", exp);
        }
        
    }
    
    private void sendEmailForExceptionalTickets(String content) {
        
        String smtpHost = attributes.getAttribute(ParamNameDef.MAIL_SERVER_HOST, "");
        String user = attributes.getAttribute(ParamNameDef.MAIL_SERVER_USER, "");
        String passwd = attributes.getAttribute(ParamNameDef.MAIL_SERVER_PASSWD, "");
        boolean auth = attributes.getAttribute(ParamNameDef.MAIL_SERVER_AUTH, false);
        
        String subject = "异常工单提醒";
        //从配置文件读取邮件接收地址
        String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        File configFile = new File(path + File.separatorChar + "conf" + File.separatorChar + "eventrecorder.properties");
        FileInputStream in = null;
        Properties props = new Properties();
        try {
            in = new FileInputStream(configFile);
            props.load(in);
            in.close();
        }
        catch(Exception exp) {
        	TraceableException.writeLog(ErrorCode.FILE_LOAD_FAILED, "load config file failed when send email.", exp);
        }
        finally {
            CommonUtil.closeIO(in);
        }
        
        String receivers = props.getProperty("exceptional.notify.emails", "");
        if (CommonUtil.isNullOrEmpty(receivers)) {
        	return;
        }
        EMail eMail = new EMail(user, subject, receivers.split(","));
        eMail.setContent(content);
        
        MailSender mailSender = new MailSender(smtpHost, user, passwd, auth);
        try {
            mailSender.sendMail(eMail);
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.COMM_ERROR, "send email failed when found exceptional ticket.", exp);
        }
    }
}
